//
// Created by liaoyang on 2023-12-11.
//

/* -------------------------------based on serial communication protocol 20230707 edition----------------------------*/
#include "driver_communicate.h"
#include "communicate_task.h"
#include "cmsis_os.h"
#include "data_fifo.h"
#include "string.h"
#include "protocol.h"
#include "usart.h"
#include "usart_bsp.h"

extern osEventFlagsId_t refereeEventHandle;
extern osSemaphoreId_t HurtDataUpdateBinarySemHandle;
extern osSemaphoreId_t HPDataUpdateBinarySemHandle;
extern sentry_decision_info sentryDecisionMake;
uint8_t robot_data_update = 0;

//----------------------------------------------初始化-----------------------------------------------------------//
/* 避免fifo_s被多个任务同时占用 */
/* 接收数据结构体互斥量 */
static osMutexId    judge_rxdata_mutex;
const osMutexAttr_t judge_rxdata_mutex_attr      = {
        .name = "judge_rxdata_mutex"
};

/* 发送数据结构体互斥量 */
static osMutexId         judge_txdata_mutex;
const osMutexAttr_t      judge_txdata_mutex_attr = {
        .name = "judge_txdata_mutex"
};

/* 接收与传输FIFO结构体 */
static fifo_s_t     judge_rxdata_fifo;
static fifo_s_t     judge_txdata_fifo;
/* Fifo中存储数组 */
static uint8_t      judge_rxdata_buf[JUDGE_FIFO_BUF_LEN];
static uint8_t      judge_txdata_buf[JUDGE_FIFO_BUF_LEN];

/* 接收到的数据包 */
unpack_data_t     judge_unpack_obj;
/* 串口相关参数结构体(包括DMA地址) */
usart_param_struct judgement_usart;
/* 裁判系统数据保护结构体 */
judgement_protection_struct judgement_protection;
/* DMA传输数据的内存地址 */
uint8_t judge_dma_rxbuff[UART_RX_DMA_SIZE];

/*!
 * @brief 串口相关结构体初始化
 */
void judgement_uart_init(void)
{
    /* 创建收发数据互斥量 */
    judge_rxdata_mutex = osMutexNew(&judge_rxdata_mutex_attr);
    judge_txdata_mutex = osMutexNew(&judge_txdata_mutex_attr);

    /* FIFO初始化 */
    fifo_s_init(&judge_rxdata_fifo, judge_rxdata_buf, JUDGE_FIFO_BUF_LEN, judge_rxdata_mutex);
    fifo_s_init(&judge_txdata_fifo, judge_txdata_buf, JUDGE_FIFO_BUF_LEN, judge_txdata_mutex);

    /* 串口相关参数结构体配置 */
    judgement_usart.huart             = &huart6;
    judgement_usart.event             = refereeEventHandle;        //配置串口事件，便于接收到数据后在相应task中解包
    judgement_usart.tx_finish_flag    = 1;
    judgement_usart.data_fifo         = &judge_rxdata_fifo;        //接收数据FIFO结构体
    judgement_usart.buff_size         = UART_RX_DMA_SIZE;          //接收数据数组长度
    judgement_usart.buff              = judge_dma_rxbuff;          //DMA传输数据存入数组地址

    /* 结构体存放接收到的数据 */
    judge_unpack_obj.data_fifo        = &judge_rxdata_fifo;        //和judgement_usart结构体公用FIFO，在中断中将数据存入FIFO，在任务中解算FIFO中数据
    judge_unpack_obj.frame_header     = (frame_header_t *) judge_unpack_obj.protocol_packet; //数据包中信息数据
    judge_unpack_obj.index            = 0;
    judge_unpack_obj.data_len         = 0;
    judge_unpack_obj.unpack_step      = STEP_HEADER_SOF;

    //开启第一次数据接收，此时也使能了串口空闲中断
    HAL_UARTEx_ReceiveToIdle_DMA(judgement_usart.huart,judgement_usart.buff,judgement_usart.buff_size);
}



//----------------------------------------------协议处理-----------------------------------------------------------//

//裁判系统数据接收
/* 包括所有包的数据结构体 */
receive_judge_t judge_rece_mesg;

/**
  * @brief    get judgement system message
  */
uint8_t                 SupplyingFlag;

//-----------------------------------------裁判系统数据解算-----------------------------------------------------//
/**
  * @brief  根据不同包ID将数据拷贝进对应数据结构体中
  * @param  *p_frame
  * @retval None
  */
void judgement_data_handler(uint8_t *data_packet) {
    frame_header_t *p_header = (frame_header_t *) data_packet;//前五个字节为frame_header数据
    memcpy(p_header, data_packet, HEADER_LEN);

    uint16_t data_length = p_header->data_length;
    uint16_t cmd_id      = *(uint16_t *) (data_packet + HEADER_LEN);
    uint8_t  *data_addr  = data_packet + HEADER_LEN + CMD_LEN;

    switch (cmd_id) {
        case GAME_STATUS_ID:
            memcpy(&judge_rece_mesg.game_status_data, data_addr, data_length);
            break;
        case GAME_RESULT_ID:
            memcpy(&judge_rece_mesg.game_result_data, data_addr, data_length);
            break;
        case GAME_ROBOT_HP_ID://机器人血量数据
            memcpy(&judge_rece_mesg.game_robot_HP_data, data_addr, data_length);
            osSemaphoreRelease(HPDataUpdateBinarySemHandle);
            break;
        case EVENT_DATA_ID:
            memcpy(&judge_rece_mesg.event_data, data_addr, data_length);
            break;
        case EXI_SUPPLY_PROJECTILE_ACTION_ID:
            memcpy(&judge_rece_mesg.supply_projectile_action_data, data_addr, data_length);
            if (judge_rece_mesg.supply_projectile_action_data.supply_robot_id ==
                judge_rece_mesg.robot_status_data.robot_id) {
                //如果是本车在补弹
                SupplyingFlag = 1;
            } else {
                //如果不是本车在补弹
                SupplyingFlag = 0;
            }
            break;
        case REFEREE_WARNING_ID://裁判系统警告ID
            memcpy(&judge_rece_mesg.referee_warning_data, data_addr, data_length);
            break;
        case DART_REMAINING_TIME_ID://飞镖发射口计时
            memcpy(&judge_rece_mesg.dart_remaining_data, data_addr, data_length);
            break;
        case ROBOT_STATUS_ID://比赛机器人状态，10HZ
            robot_data_update = 1;
            memcpy(&judge_rece_mesg.robot_status_data, data_addr, data_length);
            dataFilter(cmd_id);
            break;
        case POWER_HEAT_DATA_ID://实时功率热量数据，50HZ
            memcpy(&judge_rece_mesg.power_heat_data, data_addr, data_length);
            dataFilter(cmd_id);
            break;
        case ROBOT_POS_ID://机器人位置，10HZ
            memcpy(&judge_rece_mesg.robot_pos_data, data_addr, data_length);
            break;
        case BUFF_ID://机器人增益，状态改变后发送
            memcpy(&judge_rece_mesg.buff_data, data_addr, data_length);
            break;
        case AIR_SUPPORT_DATA_ID:
            memcpy(&judge_rece_mesg.air_support_data, data_addr, data_length);
            break;
        case HURT_ID://伤害状态，伤害发生后发送
            memcpy(&judge_rece_mesg.hurt_data, data_addr, data_length);
            osSemaphoreRelease(HurtDataUpdateBinarySemHandle);
            break;
        case SHOOT_DATA_ID://实时射击信息，射击后发送
            memcpy(&judge_rece_mesg.shoot_data, data_addr, data_length);
            break;
        case ROBO_INTERACTION_DATA_ID://交互数据接收信息
            memcpy(&judge_rece_mesg.radar_data, data_addr, data_length);
            break;
        case PROJECTILE_ALLOWANCE_ID://允许发弹量，10Hz
            memcpy(&judge_rece_mesg.projectile_allowance_data, data_addr, data_length);
            break;
        case RFID_STATUS_ID://机器人RFID状态
            memcpy(&judge_rece_mesg.rfid_status_data, data_addr, data_length);
            break;
        case DART_CLIENT_CMD_ID://飞镖机器人客户端指令数据
            memcpy(&judge_rece_mesg.dart_client_cmd_data, data_addr, data_length);
            break;
        case CUSTOM_ROBOT_DATA_ID://自定义控制器交互数据接口
            memcpy(&judge_rece_mesg.custom_interactive_data, data_addr, data_length);
            break;
        case MAP_COMMAND_ID://客户端小地图交互数据
            memcpy(&judge_rece_mesg.map_command, data_addr, data_length);
            break;
        case REMOTE_CONTROL_ID://键盘鼠标信息
            memcpy(&judge_rece_mesg.interactive_information_data, data_addr, data_length);
            break;

        default:
            break;
    }
}

/**
  * @brief  滤掉数据包中大小异常数据
  */
void dataFilter(uint16_t cmd_id)
{
    if(cmd_id == ROBOT_STATUS_ID)
    {
        //检查等级数据是否出现问题
        if(judge_rece_mesg.robot_status_data.robot_level < judgement_protection.robot_level)
        {
            judge_rece_mesg.robot_status_data.robot_level = judgement_protection.robot_level;
        }
    }
    else if(cmd_id == POWER_HEAT_DATA_ID)
    {
        if(judge_rece_mesg.power_heat_data.chassis_power > 120.0)
        {
            judge_rece_mesg.power_heat_data.chassis_power = 120.0f;
        }
        else if(judge_rece_mesg.power_heat_data.chassis_power < 0)
        {
            judge_rece_mesg.power_heat_data.chassis_power = 0;
        }

        if(judge_rece_mesg.power_heat_data.shooter_17mm_1_barrel_heat > 700)
        {
            judge_rece_mesg.power_heat_data.shooter_17mm_1_barrel_heat = 700;
        }
        else if(judge_rece_mesg.power_heat_data.shooter_17mm_1_barrel_heat < 0)
        {
            judge_rece_mesg.power_heat_data.shooter_17mm_1_barrel_heat = 0;
        }

    }
}

/**
  * @brief  解包
  */
void unpack_fifo_data(unpack_data_t *p_obj, uint8_t sof)
{
    uint8_t byte = 0;

    while (fifo_used_count(p_obj->data_fifo))
    {
        // 获取下一个字节数据
        byte = fifo_s_get(p_obj->data_fifo);
        switch (p_obj->unpack_step)
        {
            case STEP_HEADER_SOF:
            {
                if (byte == sof)
                {
                    p_obj->unpack_step = STEP_LENGTH_LOW;
                    p_obj->protocol_packet[p_obj->index++] = byte;
                }
                else
                {
                    p_obj->index = 0;
                }
            }
                break;

            case STEP_LENGTH_LOW:
            {
                p_obj->data_len = byte;
                p_obj->protocol_packet[p_obj->index++] = byte;
                p_obj->unpack_step = STEP_LENGTH_HIGH;
            }
                break;

            case STEP_LENGTH_HIGH:
            {
                p_obj->data_len |= (byte << 8);
                p_obj->protocol_packet[p_obj->index++] = byte;
                //当收到数据长度小于协议中数据最长长度时
                if (p_obj->data_len < (PROTOCOL_DATA_MAX_SIZE))
                {
                    p_obj->unpack_step = STEP_FRAME_SEQ;
                }
                else
                {
                    // 数据帧长度异常时
                    p_obj->unpack_step = STEP_HEADER_SOF;
                    p_obj->index       = 0;
                }
            }
                break;

            case STEP_FRAME_SEQ:
            {
                p_obj->protocol_packet[p_obj->index++] = byte;
                p_obj->unpack_step = STEP_HEADER_CRC8;
            }
                break;

            case STEP_HEADER_CRC8:
            {
                p_obj->protocol_packet[p_obj->index++] = byte;

                if (p_obj->index == HEADER_LEN)
                {
                    //帧头CRC校验正常时
                    if (verify_crc8_check_sum(p_obj->protocol_packet, HEADER_LEN))
                    {
                        p_obj->unpack_step = STEP_DATA_CRC16;
                    }
                    else
                    {
                        //帧头CRC校验异常，返回初始时
                        p_obj->unpack_step = STEP_HEADER_SOF;
                        p_obj->index       = 0;
                    }
                }
                else
                {
                    //收到frame_header长度异常
                    p_obj->unpack_step = STEP_HEADER_SOF;
                    p_obj->index       = 0;
                }
            }
                break;

            case STEP_DATA_CRC16:
            {
                if (p_obj->index < (HEADER_LEN + CMD_LEN + p_obj->data_len + CRC_LEN))
                {
                    p_obj->protocol_packet[p_obj->index++] = byte;
                }

                if (p_obj->index >= (HEADER_LEN + CMD_LEN + p_obj->data_len + CRC_LEN))
                {
                    p_obj->unpack_step = STEP_HEADER_SOF;
                    p_obj->index       = 0;

                    if (verify_crc16_check_sum(p_obj->protocol_packet,HEADER_LEN + CMD_LEN + p_obj->data_len + CRC_LEN))
                    {
                        //命令码
                        uint16_t cmd_id  = *(uint16_t *) (p_obj->protocol_packet + HEADER_LEN);
                        //开始数据解算
                        judgement_data_handler(p_obj->protocol_packet);
                        //数据正常，存入保护数组
                        judgement_protect_handler(cmd_id);
                    }
                }
            }
                break;

            default:
            {
                p_obj->unpack_step = STEP_HEADER_SOF;
                p_obj->index       = 0;
            }
                break;
        }
    }
}

/**
  * @brief  收到数据时存入保护数组，当裁判系统数据丢失时可使用最后一次裁判系统传来数据
  */
void judgement_protect_handler(uint16_t cmd_id)
{
    judgement_protection.judgement_lost_flag = 0;
    switch(cmd_id)
    {
        case ROBOT_STATUS_ID://比赛机器人状态
            judgement_protection.robot_id = judge_rece_mesg.robot_status_data.robot_id;
            judgement_protection.robot_level = judge_rece_mesg.robot_status_data.robot_level;
            judgement_protection.shooter_barrel_cooling_value = judge_rece_mesg.robot_status_data.shooter_barrel_cooling_value;
            judgement_protection.shooter_barrel_heat_limit = judge_rece_mesg.robot_status_data.shooter_barrel_heat_limit;
            judgement_protection.chassis_power_limit = judge_rece_mesg.robot_status_data.chassis_power_limit;
            break;
        case BUFF_ID://机器人增益
            judgement_protection.attack_buff = judge_rece_mesg.buff_data.attack_buff;
            judgement_protection.recovery_buff = judge_rece_mesg.buff_data.recovery_buff;
            judgement_protection.cooling_buff = judge_rece_mesg.buff_data.cooling_buff;
            judgement_protection.defence_buff = judge_rece_mesg.buff_data.defence_buff;
            break;
        default:
            break;
    }

}

/**
  * @brief  将DMA　buffer中数据传给FIFO
  */
void usart_rx_processed(usart_param_struct * _param,uint16_t Size)
{
    static uint8_t Rx_buf_pos = 0;	//本次回调接收的数据在缓冲区的起点
    uint32_t Rx_length = 0;	    //本次回调接收数据的长度

    /* 该段代码逻辑如下
     * 存在多个包数据传输间间隔太短使得无法获得空闲中断情况，故DMA数组第一位不一定为帧头，而可能为上一次数据
     * 由于buffer中数据是累计的，Size为当前DMA buffer中数据多少
     * 当Size比当前保持位置Rx_buf_pos大时，本次收到实际数据为Rx_buf_pos到Size处数据并将其放入FIFO中
     * 当Size比当前保持数据Rx_buf_pos小时，说明buffer已经装满后重写开始从头写入,故需要将Rx_buf_pos到buff_size位置数据放入FIFO，再将从头0到Size的数据再写入
     * */
    if (Size != Rx_buf_pos)
    {
        if (Size > Rx_buf_pos)
        {
            Rx_length = Size - Rx_buf_pos;
            fifo_s_puts(_param->data_fifo,&_param->buff[Rx_buf_pos], Rx_length);
        }
        else
        {
            Rx_length = _param->buff_size - Rx_buf_pos;
            fifo_s_puts(_param->data_fifo,&_param->buff[Rx_buf_pos], Rx_length);
            if (Size > 0)
            {
                fifo_s_puts(_param->data_fifo,&_param->buff[0], Size);
                Rx_length += Size;
            }
        }
    }
    Rx_buf_pos = Size;
    //事件置位，说明收到数据，允许unpack_task开始解包
    osEventFlagsSet(_param->event,UART_IDLE_SIGNAL);
}


///-----------------------------------------发送数据给裁判系统-----------------------------------------------------///
/* 所有包数据结构体 */
sentry_cmd_t sentry_cmd;
extern sentry_to_robot sentryToRobot;
extern enemy_coo enemyCoo;
custom_info_t sentry_to_engineer;
custom_info_t sentry_to_hero;

/* 交互数据 */
robot_interaction_data_t sentry_decision_to_judge;
robot_interaction_data_t sentry_state_to_aerial;
robot_interaction_data_t sentry_state_to_radar;
/* 存储机器人交互数据 */
uint8_t tx_buf[PROTOCOL_FRAME_MAX_SIZE];

/*!
 * @brief 将数据打包存入tx_buf数组
 * @param cmd_id 裁判系统命令码
 * @param p_data  数据源
 * @param len 有效数据长度
 * @param tx_buf 将数据打包存入的数组
 * @param robot_interaction_data_ 机器人交互数据包(0x0301)
 * @return
 */
uint8_t *protocol_packet_pack(uint16_t cmd_id, uint8_t *p_data, uint16_t len, uint8_t *tx_buf,
                              robot_interaction_data_t robot_interaction_data_) {
    uint16_t       frame_length = HEADER_LEN + CMD_LEN + len + CRC_LEN + INTERACTIVE_HEADER_LEN;
    frame_header_t *p_header    = (frame_header_t *) tx_buf;

    p_header->sof         = DN_REG_ID;
    p_header->data_length = len + 6;
    p_header->seq         = 0;

    memcpy(&tx_buf[HEADER_LEN], (uint8_t *) &cmd_id, CMD_LEN);
    append_crc8_check_sum(tx_buf, HEADER_LEN);
    memcpy(&tx_buf[HEADER_LEN + CMD_LEN], (uint8_t *) &robot_interaction_data_, INTERACTIVE_HEADER_LEN);
    memcpy(&tx_buf[HEADER_LEN + CMD_LEN + INTERACTIVE_HEADER_LEN], p_data, len);
    append_crc16_check_sum(tx_buf, frame_length);
    return tx_buf;
}


/*!
 * @brief 将机器人交互数据打包
 * @param cmd_id 裁判系统命令码
 * @param p_data 数据源
 * @param len    数据长度
 * @param robot_interaction_data 机器人交互数据包(0x0301)
 */
void data_packet_pack(uint16_t cmd_id, uint8_t *p_data, uint16_t len,
                      robot_interaction_data_t robot_interaction_data_)
{
    //包长度5+2+len+2
    uint16_t frame_length = HEADER_LEN + CMD_LEN + len + CRC_LEN + INTERACTIVE_HEADER_LEN;

    protocol_packet_pack(cmd_id, p_data, len, tx_buf, robot_interaction_data_);

    //数据从tx_buf存入fifo
    fifo_s_puts(&judge_txdata_fifo, tx_buf, frame_length);
}


/*!
 * @brief 将数据打包存入tx_buf数组
 * @param cmd_id 裁判系统命令码
 * @param p_data  数据源
 * @param len 有效数据长度
 * @param tx_buf 将数据打包存入的数组
 * @return
 */
uint8_t *protocol_packet_pack(uint16_t cmd_id, uint8_t *p_data, uint16_t len, uint8_t *tx_buf) {
    uint16_t       frame_length = HEADER_LEN + CMD_LEN + len + CRC_LEN;
    frame_header_t *p_header    = (frame_header_t *) tx_buf;

    p_header->sof         = DN_REG_ID;
    p_header->data_length = len;
    p_header->seq         = 0;

    memcpy(&tx_buf[HEADER_LEN], (uint8_t *) &cmd_id, CMD_LEN);
    append_crc8_check_sum(tx_buf, HEADER_LEN);
    memcpy(&tx_buf[HEADER_LEN + CMD_LEN], p_data, len);
    append_crc16_check_sum(tx_buf, frame_length);
    return tx_buf;
}


/*!
 * @brief 将机UI数据打包
 * @param cmd_id 裁判系统命令码
 * @param p_data 数据源
 * @param len    数据长度
 */
void ui_packet_pack(uint16_t cmd_id, uint8_t *p_data, uint16_t len)
{
    //包长度5+2+len+2
    uint16_t frame_length = HEADER_LEN + CMD_LEN + len + CRC_LEN;

    protocol_packet_pack(cmd_id, p_data, len, tx_buf);

    //数据从tx_buf存入fifo
    fifo_s_puts(&judge_txdata_fifo, tx_buf, frame_length);
}


/*!
 * @brief 将数据从FIFO中取出存入data_buf并发送
 * @param pfifo 发送数据FIFO
 * @param sof 帧头
 * @return
 */
uint32_t send_packed_fifo_data(uint8_t sof) {
    uint8_t  data_buf[JUDGE_FIFO_BUF_LEN];
    uint32_t fifo_count = fifo_used_count(&judge_txdata_fifo);
    if (fifo_count)
    {
        fifo_s_gets(&judge_txdata_fifo, data_buf, fifo_count);
        if (sof == DN_REG_ID)
            usart_dma_send(&judgement_usart, data_buf, fifo_count);
        else
            return 0;
    }
    return fifo_count;
}


void sentry_cmd_judge_update(void){
    //蓝方时
    if(judge_rece_mesg.robot_status_data.robot_id == BLUE_SENTRY_ID)
    {
        sentry_decision_to_judge.sender_ID = BLUE_SENTRY_ID;
    }

    //红方时
    if(judge_rece_mesg.robot_status_data.robot_id == RED_SENTRY_ID)
    {
        sentry_decision_to_judge.sender_ID = RED_SENTRY_ID;
    }

    sentry_decision_to_judge.receiver_ID = JUDGE_SYSTEM_SERVER_ID;
    sentry_decision_to_judge.data_cmd_id = SENTRY_AUTO_DECISION_ID;

    sentry_cmd.is_confirm_revive = sentryDecisionMake.is_confirm_revive;
    sentry_cmd.is_exchange_immediate_revive = sentryDecisionMake.is_exchange_immediate_revive;
    sentry_cmd.exchange_ammo_amount = sentryDecisionMake.exchange_ammo_amount;
    sentry_cmd.remote_exchange_ammo_request_count = sentryDecisionMake.remote_exchange_ammo_request_count;
    sentry_cmd.remote_exchange_health_request_count = sentryDecisionMake.remote_exchange_health_request_count;

    //完成数据打包，允许发送
    data_packet_pack(ROBO_INTERACTION_DATA_ID, (uint8_t *)&sentry_cmd,sizeof(sentry_cmd), sentry_decision_to_judge);
    osEventFlagsSet(refereeEventHandle,UART_TX_SIGNAL);
}


void sentry_to_aerial_update(void){
    //蓝方时
    if(judge_rece_mesg.robot_status_data.robot_id == BLUE_SENTRY_ID)
    {
        sentry_state_to_aerial.sender_ID = BLUE_SENTRY_ID;
        sentry_state_to_aerial.receiver_ID = BLUE_AERIAL_ID;
    }

    //红方时
    if(judge_rece_mesg.robot_status_data.robot_id == RED_SENTRY_ID)
    {
        sentry_state_to_aerial.sender_ID = RED_SENTRY_ID;
        sentry_state_to_aerial.receiver_ID = RED_AERIAL_ID;
    }

    sentry_state_to_aerial.data_cmd_id = 0x210;     //与飞机通信id

    //完成数据打包，允许发送
    data_packet_pack(ROBO_INTERACTION_DATA_ID, (uint8_t *)&sentryToRobot,sizeof(sentryToRobot), sentry_state_to_aerial);
    osEventFlagsSet(refereeEventHandle,UART_TX_SIGNAL);
}


void sentry_to_radar_update(void){
    //蓝方时
    if(judge_rece_mesg.robot_status_data.robot_id == BLUE_SENTRY_ID)
    {
        sentry_state_to_radar.sender_ID = BLUE_SENTRY_ID;
        sentry_state_to_radar.receiver_ID = BLUE_RADAR_ID;
    }

    //红方时
    if(judge_rece_mesg.robot_status_data.robot_id == RED_SENTRY_ID)
    {
        sentry_state_to_radar.sender_ID = RED_SENTRY_ID;
        sentry_state_to_radar.receiver_ID = RED_RADAR_ID;
    }

    sentry_state_to_radar.data_cmd_id = 0x202;     //与雷达通信id

    //完成数据打包，允许发送
    data_packet_pack(ROBO_INTERACTION_DATA_ID, (uint8_t *)&enemyCoo,sizeof(enemyCoo), sentry_state_to_radar);
    osEventFlagsSet(refereeEventHandle,UART_TX_SIGNAL);
}

void sentry_draw_ui_to_engineer(){
    //蓝方时
    if(judge_rece_mesg.robot_status_data.robot_id == BLUE_SENTRY_ID)
    {
        sentry_to_engineer.sender_id = BLUE_SENTRY_ID;
        sentry_to_engineer.receiver_id = BLUE_ENGINEER_CUSTOM_ID;
    }

    //红方时
    if(judge_rece_mesg.robot_status_data.robot_id == RED_SENTRY_ID)
    {
        sentry_to_engineer.sender_id = RED_SENTRY_ID;
        sentry_to_engineer.receiver_id = RED_ENGINEER_CUSTOM_ID;
    }

    //完成数据打包，允许发送
    ui_packet_pack(UI_DATA_ID, (uint8_t *)&sentry_to_engineer,sizeof(sentry_to_engineer));
    osEventFlagsSet(refereeEventHandle,UART_TX_SIGNAL);
}

void sentry_draw_ui_to_hero(){
    //蓝方时
    if(judge_rece_mesg.robot_status_data.robot_id == BLUE_SENTRY_ID)
    {
        sentry_to_hero.sender_id = BLUE_SENTRY_ID;
        sentry_to_hero.receiver_id = BLUE_HERO_CUSTOM_ID;
    }

    //红方时
    if(judge_rece_mesg.robot_status_data.robot_id == RED_SENTRY_ID)
    {
        sentry_to_hero.sender_id = RED_SENTRY_ID;
        sentry_to_hero.receiver_id = RED_HERO_CUSTOM_ID;
    }

    //完成数据打包，允许发送
    ui_packet_pack(UI_DATA_ID, (uint8_t *)&sentry_to_hero,sizeof(sentry_to_hero));
    osEventFlagsSet(refereeEventHandle,UART_TX_SIGNAL);
}






uint8_t get_utf8_bytes(uint8_t utf8)
{
    for (uint8_t i = 0; i < 6; i++) {
        if ((utf8 & (0x80 >> i)) == 0) {
            return i == 0? 1: i;
        }
    }

    return 1;
}

uint16_t utf8_TO_utf16(uint8_t *in, uint16_t inLen, uint16_t *out, uint16_t outLen)
{
    uint16_t length = 0;
    uint8_t bytes = 0;

    for (uint16_t i = 0; i < inLen && length < outLen; i++, length++) {
        bytes = get_utf8_bytes(in[i]);

        if (bytes > 1) {
            out[length] = in[i] & (0xFF >> (bytes + 1));
            for (uint8_t j = 1; j < bytes; j++) {
                i++;
                out[length] <<= 6;
                out[length] += in[i] & 0x3F;
            }
        } else {
            out[length] = in[i];
        }
    }

    out[length] = 0;
    return length;
}